package org.jground.rx.ui.zk.viewControl;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jground.rx.IRXObject;
import org.jground.rx.RXAttribute;
import org.jground.rx.RXObjectService;
import org.jground.rx.RXSystem;
import org.jground.rx.RXTypeForeach;
import org.jground.rx.RXView;
import org.jground.rx.ui.zk.UIEditPanel;
import org.jground.rx.ui.zk.UIFrame;
import org.jground.rx.ui.zk.UIResultList;
import org.jground.rx.ui.zk.UIStyles;
import org.jground.util.ArrayUtils;
import org.jground.util.CollectionUtils;
import org.jground.util.StringUtils;
import org.jground.zk.zulX.HboxX;
import org.jground.zk.zulX.VboxX;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.event.Events;
import org.zkoss.zul.Button;
import org.zkoss.zul.Listcell;

public class UIAttributeControlForeach extends UIAttributeControlBase implements EventListener {

    private static Log logger = LogFactory.getLog(UIAttributeControlForeach.class);

    public UIAttributeControlForeach createNew(UIFrame uiFrame, RXView moControl) {
        return new UIAttributeControlForeach(uiFrame, moControl);
    }

    public UIAttributeControlForeach() {}

    // RX
    private RXAttribute moAttribute;
    private String compMoid;
    private String attref;
    private String attrefBack;

    // TARGET
    private String[] targetOids;
    private UIResultList targetDataList;

    // COMP
    private List<String> compOids = new ArrayList<String>();
    private UIEditPanel compEditUI;
    private HboxX compEditPanel;
    private HboxX buttonPanel;
    private Button newBt;
    private Button doneBt;
    private Button cancelBt;
    private Button deleteBt;
    private boolean isEditPanelOpen;
    private IRXObject currentModOnEdit;

    //

    private UIAttributeControlForeach(UIFrame uiFrame, RXView moControl) {
        super(uiFrame, moControl);
        this.moAttribute = moControl.getRXAttribute();

        RXTypeForeach moTypeForeach = (RXTypeForeach) moAttribute.getRXType().getBaseType();
        compMoid = moTypeForeach.getCompType().getLookupMoid();
        attref = moTypeForeach.getAttref();
        attrefBack = moTypeForeach.getCompType().getAttrefBack();
        //
        //
        targetDataList = new UIResultList(uiFrame);
        SelectionListener renderer = new SelectionListener();
        targetDataList.setExternalEventListener(renderer);
        //
        compEditUI = new UIEditPanel(uiFrame, compMoid);
        compEditPanel = new HboxX();
        newBt = new Button("New");
        doneBt = new Button("Done");
        cancelBt = new Button("Cancel");
        deleteBt = new Button("Delete");
        buttonPanel = new HboxX();
        buttonPanel.setSclass(UIStyles.BUTTONGROUP);
        //
        add(new VboxX(UIResultList.uiBox(targetDataList), compEditPanel, buttonPanel));
        //
        doneBt.addEventListener(Events.ON_CLICK, this);
        cancelBt.addEventListener(Events.ON_CLICK, this);
        deleteBt.addEventListener(Events.ON_CLICK, this);
        newBt.addEventListener(Events.ON_CLICK, this);
        //
        closeEditPanel(); //
    }

    public void set(String... values) {
        updateTargets();
        CollectionUtils.set(compOids, values);
        closeEditPanel();
    }

    private void updateTargets() {
        targetDataList.removeAllObject();
        IRXObject context = getDataContext();
        targetOids = context.getValues(attref);
        List<IRXObject> foreachMods = RXObjectService.getInstance().getByIds(targetOids);
        targetDataList.addObjects(foreachMods);
    }

    public String[] get() {
        updateTargets();
        List<String> newCompOids = new ArrayList<String>();
        for (String compOid : compOids) {
            IRXObject componentRxd = getDataContext().getComponentById(compOid);
            if (componentRxd != null) {
                String referred = componentRxd.getCurrentValue(attrefBack);
                if (ArrayUtils.contains(targetOids, referred)) {
                    CollectionUtils.addUnique(newCompOids, compOid);
                }
            }
        }
        CollectionUtils.set(compOids, newCompOids);
        return newCompOids.toArray(StringUtils.EMPTY_STRING_ARRAY);
    }

    public void clear() {
        targetDataList.removeAllObject();
        compOids.clear();
    }

    public void onEvent(Event he) {
        if (he.getTarget() == doneBt) {
            update();
            closeEditPanel();
            currentModOnEdit = null;
        }
        if (he.getTarget() == cancelBt) {
            closeEditPanel();
            currentModOnEdit = null;
        }
        if (he.getTarget() == deleteBt) {
            closeEditPanel();
            compOids.remove(currentModOnEdit.getOidString());
            currentModOnEdit = null;
        }
    }

    private void closeEditPanel() {
        compEditUI.clearData();
        compEditPanel.removeAll();
        buttonPanel.removeAll();
        isEditPanelOpen = false;
    }

    public void openEditPanel() {

        compEditPanel.set(compEditUI.getView());
        buttonPanel.set(doneBt, deleteBt, cancelBt);
        isEditPanelOpen = true;

    }

    private boolean isEditPanelOpen() {
        return isEditPanelOpen;
    }

    private IRXObject getOrCreateComp(String targetOid) {
        IRXObject context = getDataContext();
        IRXObject componentRxd = null;
        for (String compOid : this.compOids) {
            componentRxd = context.getComponentById(compOid);
            if (componentRxd == null) {
                logger.warn("Comp object not found " + compMoid + " " + compOid + " for " + targetOid + " in context "
                        + context);
                continue;
            }
            String attrefBackValue = componentRxd.getCurrentValue(attrefBack);
            if (targetOid.equals(attrefBackValue)) {
                return componentRxd;
            } else {
                componentRxd = null;
            }
        }
        if (componentRxd == null) {
            componentRxd = context.newComponent(RXSystem.getInstance().getRxService().getRXClass(compMoid));
            componentRxd.checkOut();
            componentRxd.set(attrefBack, targetOid);
        }
        componentRxd.checkOut();
        return componentRxd;
    }

    public void update() {
        if (isEditPanelOpen()) {
            //IRXObject context = getDataContext();
            IRXObject componentRxd = compEditUI.getData();
            //context.addToCompCache(componentRxd);
            CollectionUtils.addUnique(compOids, componentRxd.getOidString());
        }
    }

    public class SelectionListener implements // ListitemRenderer,
            EventListener {

        public void onEvent(Event h) {
            if (h.getTarget() instanceof Listcell) {
                Listcell cell = (Listcell) h.getTarget();
                String targetOid = cell.getAttribute("oid").toString();
                currentModOnEdit = getOrCreateComp(targetOid);
                compEditUI.setData(currentModOnEdit);
                openEditPanel();
            }
        }

    }
}
